#include "tts_thread.h"
#include <unistd.h>

#include <regex>

#include <string>

#include <algorithm>

// #define PEOPLE_ID       47
#define PEOPLE_ID       0

#define SPEAKER_SPEED   0.85f

#define SLEEP_PERIOD_MS 20



#define SCALE_FACTOR_MAX     20.0f

namespace {
    std::string convertPercentage(std::string &input) {
        sys_log("origin: %s", input.c_str());

        // 转换百分号
        std::regex percentRegex(R"((\d+(?:\.\d+)?)%)");
        std::string inDelPer = std::regex_replace(input, percentRegex, "百分之$1");

        // // 正则表达式匹配数字+点+数字的模式
        // std::regex pattern(R"((\d+)\.(\d+))");

        // // 替换为"$1点$2"，其中$1和$2分别对应捕获的第一个和第二个数字组
        // std::string result = std::regex_replace(inDelPer, pattern, "$1点$2");

        return inDelPer;

    }
};

// using namespace webrtc;

// 构造函数
TtsThread::TtsThread(void)
    : tts_engine_() {
    
    audioStop();
    
    tts_thread_ = std::thread(&TtsThread::ttsThread, this);
}


// 析构函数
TtsThread::~TtsThread() {
    sys_log("tts is been destoryed. start......");

    exitFlag = true;

    cv_.notify_all();  // thread wakeup to exit

    if (tts_thread_.joinable()) {
        sys_log("waiting for destorying tts thread.");
        tts_thread_.join(); // 等待 TTS 线程结束, 回收线程资源
        sleep(1);
    }
    sys_log("tts is been destoryed. end......");
}


// 添加文本到队列
void TtsThread::appendText(const std::string& text) {

    std::unique_lock<std::mutex> lock(queue_mutex_);

    audio_dataset_.append(text);

    // sys_log("add text(%s) to dataset.", text.c_str());

    cv_.notify_one();
}


static const std::regex CUR_TIME("目前");

// TTS 线程函数
void TtsThread::ttsThread() {
    static std::string audio_str;

    while (!exitFlag) {
        std::unique_lock<std::mutex> lock(queue_mutex_);

        cv_.wait(lock, [this]() {
            bool is_deal = false;
            audio_str = audio_dataset_.nextSentence(is_deal);
            return exitFlag || is_deal;
        });

        lock.unlock();

        // 等待一段时间，不要运行的那么块
        // std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_PERIOD_MS));
        // sys_log("cv data:[%s]", audio_str.c_str());

        // 去除前后的空格
        audio_str.erase(std::remove_if(audio_str.begin(), audio_str.end(), ::isspace), audio_str.end());

        if (audio_str.empty() || audio_str == "。") { 
            continue;
        }

        if (exitFlag) break;  // manual exit point

        // sys_log("origin: %s", audio_str.c_str());

        // 进行正则表达式匹配，转换百分号
        std::string out_str = convertPercentage(audio_str);
        // std::string out_str = audio_str;

        sys_log("transforming str to audio: [%s]", out_str.c_str());

        // 词语修补
        out_str = std::regex_replace(out_str, CUR_TIME, " ");

        // 将字符串生成音频
        std::vector<float> audio_data = tts_engine_.generate(out_str, 
            PEOPLE_ID, 
            SPEAKER_SPEED);

        if (exitFlag) break;  // manual exit point


        // =====================================================================
        // 对音频数据进行缩放，缓解声音忽大忽小的问题  begin >>>>>>>>>>>>>>>>>>>>>>>>>
        // =====================================================================
        static float max_audio_pp = 0.8f;

        // 计算音频数据中的最大绝对值
        float max_value = 0.0f;
        for (float sample : audio_data) {
            max_value = std::max(max_value, std::abs(sample));
        }

        // 计算缩放比例
        float scale_factor = (max_value > 0.0f) ? (max_audio_pp / max_value) : 1.0f;

        if (scale_factor > SCALE_FACTOR_MAX) {
            
            warn_log("scale factor too large: %.2f -> %.2f", scale_factor, SCALE_FACTOR_MAX);
            scale_factor = SCALE_FACTOR_MAX; 
        } else {
            // sys_log("scale factor: %.2f", scale_factor);
        }

        // 对音频数据进行缩放
        for (float &sample : audio_data) {
            sample *= scale_factor;
        }
        // =====================================================================
        // 对音频数据进行缩放，缓解声音忽大忽小的问题  end <<<<<<<<<<<<<<<<<<<<<<<<<<<
        // =====================================================================

        // 在音频数据后面添加一些静音数据
        audio_data.resize(audio_data.size() + 2000, 0);

        // 将合成的音频数据送到音频播放器
        audio_player_.pushAudio(audio_data);

    }
}
